3/links: Links and Auxiliary Files.
@Purpose: To manage links to auxiliary files, and placeholder variables.
@Interface:
-- Owns struct auxiliary_file (private)
@Definitions:
@ Auxiliary files are for items bundled up with the release but which are
deliberately made accessible for the eventual player: things such as maps
or manuals. |cblorb| needs to know about these only when releasing a website;
they are also recorded in an iFiction record, but |cblorb| does not create
that (|ni| does).
@c
typedef struct auxiliary_file {
char relative_URL[MAX_FILENAME_LENGTH];
char full_filename[MAX_FILENAME_LENGTH];
char aux_leafname[MAX_FILENAME_LENGTH];
char description[MAX_FILENAME_LENGTH];
char format[MAX_EXTENSION_LENGTH]; /* e.g., ``jpg'', ``pdf'' */
MEMORY_MANAGEMENT
} auxiliary_file;
@-------------------------------------------------------------------------------
@p Registration.
The format text is set to a lower-case version of the filename extension,
and the URL to the filename itself; except when there is no extension, so
that the auxiliary resource is a mini-website in a subfolder of the release
website. In that case the format is |link| and the URL is to the index file
in the subfolder.
@c
/**/ void create_auxiliary_file(char *filename, char *description) {
auxiliary_file *aux = CREATE(auxiliary_file);
strcpy(aux->description, description);
strcpy(aux->full_filename, filename);
char *ext = get_filename_extension(filename);
char *leaf = get_filename_leafname(filename);
if (ext[0] == '.') {
strcpy(aux->relative_URL, filename);
if (strlen(ext + 1) >= MAX_EXTENSION_LENGTH - 1) {
error("auxiliary file has overlong extension"); return;
}
strcpy(aux->format, ext + 1);
int k; for (k=0; aux->format[k]; k++) aux->format[k] = tolower(aux->format[k]);
} else {
strcpy(aux->format, "link");
sprintf(aux->relative_URL, "%s%cindex.html", filename, SEP_CHAR);
}
strcpy(aux->aux_leafname, leaf);
printf("! Auxiliary file: <%s> = <%s>\n", filename, description);
}
@p Linking.
The list of links to auxiliary resources is written using |
...|
list entry tags, for convenience of CSS styling.
@c
void expand_AUXILIARY_variable(FILE *COPYTO) {
auxiliary_file *aux;
LOOP_OVER(aux, auxiliary_file) {
fprintf(COPYTO, "");
download_link(COPYTO,
aux->description, aux->full_filename, aux->aux_leafname, aux->format);
fprintf(COPYTO, "");
}
add_links_to_requested_resources(COPYTO);
}
@ On some of the pages produced by |cblorb| the story file itself looks like
another auxiliary resource, but it's produced thus:
@c
void expand_DOWNLOAD_variable(FILE *COPYTO) {
char target_pathname[MAX_FILENAME_LENGTH]; /* eventual pathname of Blorb file written */
sprintf(target_pathname, "%s%c%s", release_folder, SEP_CHAR, read_placeholder("STORYFILE"));
download_link(COPYTO, "Story File", target_pathname, read_placeholder("STORYFILE"), "Blorb");
}
@p Links.
This routine, then, handles either kind of link.
@c
/**/ void download_link(FILE *COPYTO, char *desc, char *filename, char *relative_url, char *form) {
int size_up = TRUE;
if (strcmp(form, "link") == 0) size_up = FALSE;
fprintf(COPYTO, "%s ", relative_url, desc);
open_style(COPYTO, "filetype");
fprintf(COPYTO, "(%s", form);
if (size_up) {
long int size = -1L;
if (strcmp(desc, "Story File") == 0) size = (long int) blorb_file_size;
else size = file_size(filename);
if (size != -1L) @
}
fprintf(COPYTO, ")");
close_style(COPYTO, "filetype");
}
@ We round down to the nearest KB, MB, GB, TB or byte, as appropriate. Although
this will describe a 1-byte auxiliary file as ``1 bytes'', the contingency seems
remote.
@ =
char *units = " bytes";
long int remainder = 0;
if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = "KB"; }
if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = "MB"; }
if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = "GB"; }
if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = "TB"; }
fprintf(COPYTO, ", %d", (int) size);
if ((size < 100L) && (remainder >= 103L)) fprintf(COPYTO, ".%d", (int) (remainder/103L));
fprintf(COPYTO, "%s", units);
@p Cover image.
Note that if the large cover image is a PNG, so is the small (thumbnail)
version, and vice versa -- supplying ``Cover.jpg'' and ``Small Cover.png''
will not work.
@c
void expand_COVER_variable(FILE *COPYTO) {
if (cover_exists) {
char *format = "png"; if (cover_is_in_JPEG_format) format = "jpg";
fprintf(COPYTO, "",
format, format);
}
}
@p Releasing.
When we generate a website, we need to copy the auxiliary files into it
(though not mini-websites: the user will have to do that).
@c
/**/ void request_copy_of_auxiliaries(void) {
auxiliary_file *aux;
LOOP_OVER(aux, auxiliary_file)
if (strcmp(aux->format, "link") != 0) {
if (trace_mode)
printf("! COPY <%s> as <%s>\n", aux->full_filename, aux->aux_leafname);
request_copy(aux->full_filename, aux->aux_leafname);
}
}